home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / cp.c < prev    next >
C/C++ Source or Header  |  1990-07-15  |  4KB  |  211 lines

  1. /* cp - copy files        Author: Andy Tanenbaum */
  2.  
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include <fcntl.h>
  6.  
  7. #define TRANSFER_UNIT    16384
  8. char cpbuf[TRANSFER_UNIT];
  9. int isfloppy;            /* set to 1 for cp x /dev/fd? */
  10.  
  11.  
  12. main(argc, argv)
  13. int argc;
  14. char *argv[];
  15. {
  16.   int fd1, fd2, m, s;
  17.   struct stat sbuf, sbuf2;
  18.  
  19.   if (argc < 3) usage();
  20.  
  21.   /* Get the status of the last named file.  See if it is a directory. */
  22.   s = stat(argv[argc - 1], &sbuf);
  23.   m = sbuf.st_mode & S_IFMT;
  24.   if (s >= 0 && m == S_IFDIR) {
  25.     /* Last argument is a directory. */
  26.     exit(cp_to_dir(argc, argv));
  27.   } else if (argc > 3) {
  28.     /* More than 2 arguments and last one is not a directory. */
  29.     usage();
  30.   } else if (s < 0 || m == S_IFREG || m == S_IFCHR || m == S_IFBLK) {
  31.     /* Exactly two arguments.  Check for cp f1 f1. */
  32.     if (equal(argv[1], argv[2])) {
  33.         std_err("cp: cannot copy a file to itself\n");
  34.         exit(-1);
  35.     }
  36.  
  37.     /* Command is of the form cp f1 f2. */
  38.     fd1 = open(argv[1], O_RDONLY);
  39.     if (fd1 < 0) {
  40.         stderr3("cannot open ", argv[1], "\n");
  41.         exit(1);
  42.     }
  43.     fstat(fd1, &sbuf);
  44.     m = sbuf.st_mode & S_IFMT;
  45.     if (m == S_IFDIR) {
  46.         stderr3("<", argv[1], "> directory\n");
  47.         exit(1);
  48.     }
  49.     fd2 = creat(argv[2], sbuf.st_mode & 0777);
  50.     if (fd2 < 0) {
  51.         stderr3("cannot create ", argv[2], "\n");
  52.         exit(2);
  53.     }
  54.     fstat(fd2, &sbuf2);
  55.     if ((sbuf2.st_mode & S_IFMT) == S_IFBLK) isfloppy = 1;
  56.     copyfile(fd1, fd2, argv[2]);
  57.   } else {
  58.     stderr3("cannot copy to ", argv[2], "\n");
  59.     exit(3);
  60.   }
  61.   exit(0);
  62. }
  63.  
  64.  
  65.  
  66.  
  67.  
  68. cp_to_dir(argc, argv)
  69. int argc;
  70. char *argv[];
  71. {
  72.   int i, mode, fd1, fd2, exit_status = 0;
  73.   char dirname[256], *ptr, *dp;
  74.   struct stat sbuf;
  75.  
  76.   for (i = 1; i < argc - 1; i++) {
  77.     fd1 = open(argv[i], O_RDONLY);
  78.     if (fd1 < 0) {
  79.         stderr3("cannot open ", argv[i], "\n");
  80.         exit_status = 1;
  81.         continue;
  82.     }
  83.     ptr = argv[argc - 1];
  84.     dp = dirname;
  85.     while (*ptr != 0) *dp++ = *ptr++;
  86.  
  87.     *dp++ = '/';
  88.     ptr = argv[i];
  89.  
  90.     /* Concatenate dir and file name in dirname buffer. */
  91.     while (*ptr != 0) ptr++;/* go to end of file name */
  92.     while (ptr > argv[i] && *ptr != '/') ptr--;    /* get last component */
  93.     if (*ptr == '/') ptr++;
  94.     while (*ptr != 0) *dp++ = *ptr++;
  95.     *dp++ = 0;
  96.     fstat(fd1, &sbuf);
  97.     mode = sbuf.st_mode & S_IFMT;
  98.     if (mode == S_IFDIR) {
  99.         stderr3("<", argv[i], "> directory\n");
  100.         exit_status = 1;
  101.         close(fd1);
  102.         continue;
  103.     }
  104.     fd2 = creat(dirname, sbuf.st_mode & 0777);
  105.     if (fd2 < 0) {
  106.         stderr3("cannot create ", dirname, "\n");
  107.         exit_status = 2;
  108.         close(fd1);
  109.         continue;
  110.     }
  111.     copyfile(fd1, fd2, dirname);
  112.   }
  113.   return(exit_status);
  114. }
  115.  
  116.  
  117.  
  118.  
  119.  
  120. copyfile(fd1, fd2, name)
  121. int fd1, fd2;
  122. char *name;
  123. {
  124.   int n, m, mode;
  125.   struct stat sbuf;
  126.  
  127.   do {
  128.     n = read(fd1, cpbuf, TRANSFER_UNIT);
  129.     if (n < 0) {
  130.         std_err("cp: read error\n");
  131.         break;
  132.     }
  133.     if (n > 0) {
  134.         m = write(fd2, cpbuf, n);
  135.         if (m != n) {
  136.             /* Write failed.  Don't keep truncated
  137.              * regular file. */
  138.             perror("cp");
  139.             fstat(fd2, &sbuf);    /* check for special files */
  140.             mode = sbuf.st_mode & S_IFMT;
  141.             if (mode == S_IFREG) unlink(name);
  142.             exit(1);
  143.         }
  144.         if (isfloppy) sync();    /* purge the cache all at once */
  145.     }
  146.   } while (n == TRANSFER_UNIT);
  147.   close(fd1);
  148.   close(fd2);
  149. }
  150.  
  151. usage()
  152. {
  153.   std_err("Usage:  cp f1 f2;  or  cp f1 ... fn d2\n");
  154.   exit(-1);
  155. }
  156.  
  157. typedef char *cptr;
  158.  
  159. int equal(s1, s2)
  160. char *s1, *s2;
  161. {
  162.   struct stat sb1, sb2;
  163.  
  164.   /* Same file, different name? */
  165.   stat(s1, &sb1);
  166.   stat(s2, &sb2);
  167.   if (memcmp((cptr) & sb1, (cptr) & sb2, sizeof(struct stat)) == 0)
  168.     return(1);
  169.   /* Same file, same name? */
  170.   while (1) {
  171.     if (*s1 == 0 && *s2 == 0) return(1);
  172.     if (*s1 != *s2) return (0);
  173.     if (*s1 == 0 || *s2 == 0) return (0);
  174.     s1++;
  175.     s2++;
  176.   }
  177. }
  178.  
  179. int match(s1, s2, n)
  180. char *s1, *s2;
  181. int n;
  182. {
  183.   while (n--) {
  184.     if (*s1++ != *s2++) return(0);
  185.   }
  186.   return(1);
  187. }
  188.  
  189.  
  190. stderr3(s1, s2, s3)
  191. char *s1, *s2, *s3;
  192. {
  193.   std_err("cp: ");
  194.   std_err(s1);
  195.   std_err(s2);
  196.   std_err(s3);
  197. }
  198.  
  199.  
  200. int memcmp(b1, b2, n)
  201. cptr b1, b2;
  202. int n;
  203. {
  204.   while (n--) {
  205.     if (*b1 != *b2) return((int) (*b1 - *b2));
  206.     ++b1;
  207.     ++b2;
  208.   }
  209.   return(0);
  210. }
  211.